using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using TestCases.CompareAssert.Core;
using TestCases.CompareAssert.Core.Comparers.Adapters;
using TestCases.CompareAssert.Core.Comparers.Interfaces;
using TestCases.CompareAssert.Core.Comparers.Members;
using TestCases.CompareAssert.Core.Interfaces;

namespace TestCases.CompareAssert.Settings.Interfaces
{
    public interface ICompareSetup
    {
        ICompareSetup Reset();

        #region Compare By members
        ICompareSetup CompareBy(IObjectComparer comparer);
        ICompareSetup CompareBy(IComparer comparer); // Adapter
        ICompareSetup CompareBy(IEqualityComparer comparer); // Adapter
        ICompareSetup CompareBy<T>(IEqualityComparer<T> comparer); // Adapter
        ICompareSetup CompareBy<T>(IComparer<T> comparer); // Adapter
        ICompareSetup CompareBy(CompareDelegate func); // Adapter
        ICompareSetup CompareBy<T>(CompareDelegate<T> func); // Adapter;
        #endregion
        #region Result Is members
        ICompareSetup ResultIs(CompareStatus status); // ResultSettings
        ICompareSetup ResultIs(CompareStatus status, string message); // ResultSettings
        ICompareSetup ResultIs(CompareStatus status, string message, object args); // ResultSettings
        ICompareSetup ResultIs(bool value); // ResultSettings
        ICompareSetup ResultIs(bool value, string message); // ResultSettings
        ICompareSetup ResultIs(bool value, string message, object args); // ResultSettings
        ICompareSetup ResultIs(IResultSettings result);
        #endregion
        #region Disable Comparer members
        ICompareSetup DisableComparer(string name);
        ICompareSetup DisableComparers(IEnumerable<string> comparers);
        ICompareSetup DisableComparersBy(string regex);
        ICompareSetup DisableComparersBy(Predicate<string> predicate);
        #endregion
        #region Disable Generic Comparer members
        ICompareSetup DisableGenericComparer(string name);
        ICompareSetup DisableGenericComparers(IEnumerable<string> comparers);
        ICompareSetup DisableGenericComparersBy(string regex);
        ICompareSetup DisableGenericComparersBy(Predicate<string> predicate);
        #endregion
        #region Ignore Property members
        ICompareSetup IgnoreProperty(string property);
        ICompareSetup IgnoreProperties(IEnumerable<string> properties);
        ICompareSetup IgnorePropertiesBy(string regex);
        ICompareSetup IgnorePropertiesBy(Predicate<string> predicate);
        #endregion
        #region Ignore Field members
        ICompareSetup IgnoreField(string field);
        ICompareSetup IgnoreFields(IEnumerable<string> fields);
        ICompareSetup IgnoreFieldsBy(string regex);
        ICompareSetup IgnoreFieldsBy(Predicate<string> predicate);
        #endregion
        #region Ignore Element members
        ICompareSetup IgnoreElementAt(int dimension, long index);        
        ICompareSetup IgnoreElementsAt(int dimension, long minIndex, long maxIndex);
        ICompareSetup IgnoreElementsAt(int dimension, IEnumerable<long> indexes);
        ICompareSetup IgnoreElementsBy(int dimension, Predicate<long> predicate);
        
        ICompareSetup IgnoreElementsAt(int minDimension, int maxDimension, long index);
        ICompareSetup IgnoreElementsAt(int minDimension, int maxDimension, long minIndex, long maxIndex);
        ICompareSetup IgnoreElementsAt(int minDimension, int maxDimension, IEnumerable<long> indexes);
        ICompareSetup IgnoreElementsBy(int minDimension, int maxDimension, Predicate<long> predicate);
        
        ICompareSetup IgnoreElementsAt(IEnumerable<int> dimensions, long index);
        ICompareSetup IgnoreElementsAt(IEnumerable<int> dimensions, long minIndex, long maxIndex);
        ICompareSetup IgnoreElementsAt(IEnumerable<int> dimensions, IEnumerable<long> indexes);
        ICompareSetup IgnoreElementsBy(IEnumerable<int> dimensions, Predicate<long> predicate);
        
        ICompareSetup IgnoreElementsAt(Predicate<int> dimensionPredicate, long index);
        ICompareSetup IgnoreElementsAt(Predicate<int> dimensionPredicate, long minIndex, long maxIndex);
        ICompareSetup IgnoreElementsAt(Predicate<int> dimensionPredicate, IEnumerable<long> indexes);
        ICompareSetup IgnoreElementsBy(Predicate<int> dimensionPredicate, Predicate<long> predicate);
                        
        ICompareSetup IgnoreIndex(long index); // at 0 dimension
        ICompareSetup IgnoreIndexes(IEnumerable<long> indexes); // at 0 dimension
        ICompareSetup IgnoreIndexes(long minIndex, long maxIndex); // at 0 dimension
        ICompareSetup IgnoreIndexesBy(Predicate<long> predicate); // at 0 dimension
        
        ICompareSetup IgnoreElementsBy(Predicate<long[]> predicate);
        #endregion
        #region Ignore Entry members
        ICompareSetup IgnoreEntry(object key);
        ICompareSetup IgnoreEntries(IEnumerable<object> keys);
        ICompareSetup IgnoreEntriesBy(Predicate<object> predicate);
        #endregion

        ICompareSetup IgnoreReadOnlyProperties(bool value);
        ICompareSetup ForceEqualsComparer(bool value);
        ICompareSetup ForceHashCodeComparer(bool value);
        ICompareSetup DefinePropertiesFlags(AccessFlags flags);
        ICompareSetup DefineFieldsFlags(AccessFlags flags);
        ICompareSetup CompareKeysBy(IEqualityComparer<object> comparer);   
        
    }
}